package com.ruoyi.app.controller.order.service.impl;

import com.ruoyi.app.common.utils.IdWorker;
import com.ruoyi.app.controller.member.mapper.IMemberBalanceRecordMapper;
import com.ruoyi.app.controller.member.mapper.IMemberCreditRecordMapper;
import com.ruoyi.app.controller.member.mapper.IMemberMapper;
import com.ruoyi.app.controller.order.mapper.IMemberRechargeOrderMapper;
import com.ruoyi.app.controller.order.service.IMemberRechargeOrderService;
import com.ruoyi.app.controller.product.mapper.IProductMapper;
import com.ruoyi.app.framework.manager.AsyncManager;
import com.ruoyi.app.framework.manager.factory.ApiAsyncFactory;
import com.ruoyi.common.constant.MemberCreditConstants;
import com.ruoyi.common.constant.MemberRechargeConstants;
import com.ruoyi.common.constant.OrderConstants;
import com.ruoyi.common.constant.SysConfigConstants;
import com.ruoyi.common.entity.DO.member.MemberBalanceRecordDO;
import com.ruoyi.common.entity.DO.member.MemberCreditRecordDO;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.DO.order.MemberRechargeOrderDO;
import com.ruoyi.common.entity.VO.PayVO;
import com.ruoyi.common.entity.VO.order.MemberRechargeOrderSearchVO;
import com.ruoyi.common.entity.VO.product.RechargeProductVO;
import com.ruoyi.common.entity.VO.shop.ShopProductSearchVO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.NumberUtils;
import lombok.Synchronized;
import org.apache.ibatis.annotations.Param;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW;

@Service(value = "IMemberRechargeOrderService")
public class MemberRechargeOrderServiceImpl implements IMemberRechargeOrderService {

    @Resource
    private IMemberRechargeOrderMapper rechargeOrderMapper;

    @Resource
    private IMemberBalanceRecordMapper balanceRecordMapper;

    @Resource
    private IMemberCreditRecordMapper creditRecordMapper;

    @Resource
    private IMemberMapper memberMapper;

    @Resource
    private IProductMapper productMapper;


    @Override
    public List<MemberRechargeOrderDO> searchList(MemberRechargeOrderSearchVO orderSearchVO) {
        Example example = new Example(MemberRechargeOrderDO.class);
        Example.Criteria condition = example.createCriteria();
        condition.andEqualTo("isEnable", 1).andEqualTo("isDelete", 0);
        if (null != orderSearchVO.getPayStatus()) {
            condition.andEqualTo("orderStatus", orderSearchVO.getOrderStatus());
        }
        if (null != orderSearchVO.getMemberId()) {
            condition.andEqualTo("memberId", orderSearchVO.getMemberId());
        }
        example.selectProperties("orderSn", "paySn", "amount", "payAmount", "giftCredit", "orderStatus", "createTime", "payStatus", "payTime", "cancelTime");
        return rechargeOrderMapper.selectByExample(example);
    }

    @Override
    @Synchronized
    public PayVO createOrder(MemberRechargeOrderDO createVO) {
        //查询会员等级
        Long memberVipTypeId = memberMapper.getMemberVipIdById(createVO.getMemberId());
        ShopProductSearchVO searchVO = new ShopProductSearchVO();
        searchVO.setShopId(createVO.getShopId());
        searchVO.setProductId(createVO.getProductId());
        searchVO.setIsDelete(0);
        searchVO.setIsEnable(1);
        searchVO.setMemberVipTypeId(memberVipTypeId);
        searchVO.setSystemModule(SysConfigConstants.SystemModuleEnum.RECHARGE.getValue());
        RechargeProductVO productInfo = productMapper.getRechargeProductDetail(searchVO);
        if (null == productInfo) {
            throw new BusinessException("暂不提供该金额的充值,请选择其他");
        }
        if (0 == productInfo.getStock()) {
            throw new BusinessException("该面值的充值金额已抢光");
        }
        //TODO:查看是否送积分
//        if (1 == productInfo.getIsBenefitEnable() && 1 == productInfo.getIsCredit()) {
//            if (null != productInfo.getBenefitCredit() && productInfo.getBenefitCredit() > 0) {
//                createVO.setGiftCredit(productInfo.getBenefitCredit());
//            } else if (null != productInfo.getBenefitCreditRate() && BigDecimal.ZERO.compareTo(productInfo.getBenefitCreditRate()) < 0) {
//                createVO.setGiftCredit(createVO.getAmount().multiply(productInfo.getBenefitCreditRate()).toBigInteger().intValue());
//            }
//        }
        //TODO:查看是否送金额
        if (1 == productInfo.getIsBenefitEnable() && 1 == productInfo.getIsAmount()) {
            if (null != productInfo.getBenefitAmount() && productInfo.getBenefitAmount() > 0) {
                createVO.setGiftAmount(productInfo.getBenefitAmount());
            } else if (null != productInfo.getBenefitAmountRate() && BigDecimal.ZERO.compareTo(productInfo.getBenefitAmountRate()) < 0) {
                createVO.setGiftAmount(createVO.getAmount().multiply(productInfo.getBenefitAmountRate()).toBigInteger().intValue());
            }
        }
        String time = DateUtils.dateTimeNow();
        long orderId;
        try {
            orderId = IdWorker.getFlowIdWorkerInstance().nextId();
        } catch (Exception e) {
            throw new BusinessException("网络超时,请重新再试！");
        }
        createVO.setId(orderId);
        createVO.setProductId(productInfo.getProductId());
        createVO.setProductSn(productInfo.getProductSn());
        createVO.setAmount(productInfo.getPrice());
        createVO.setDiscountAmount(BigDecimal.ZERO);
        createVO.setDiscountDesc("无");
        createVO.setPayAmount(createVO.getAmount());
        createVO.setOrderSn(OrderConstants.SnPrefix.CHARGE_MEMBER.getValue() + time + NumberUtils.generateCode(5));
        createVO.setPaySn(OrderConstants.SnPrefix.PAY_MEMBER.getValue() + time + NumberUtils.generateCode(4));
        createVO.setOrderStatus(OrderConstants.OrderStatusEnum.PRE_PAY.getValue());
        createVO.setPayStatus(OrderConstants.OrderPayStatusEnum.PRE_PAY.getValue());
        createVO.setCreateTime(new Date());
        createVO.setCreateBy("会员充值");
        rechargeOrderMapper.insertSelective(createVO);
        PayVO payVO = new PayVO();
        payVO.setPayCost(createVO.getPayAmount());
        payVO.setOrderSn(createVO.getOrderSn());
        payVO.setPaySn(createVO.getPaySn());
        return payVO;
    }

    @Override
    @Transactional(propagation = REQUIRES_NEW)
    public void payNotifyHandle(Map<String, String> notifyMap) {
        String time = DateUtils.dateTimeNow();
        Example example = new Example(MemberRechargeOrderDO.class);
        BigDecimal payCost;
        if (notifyMap.containsKey("wxAmount")) {
            payCost = new BigDecimal(notifyMap.get("wxAmount"));
            payCost = payCost.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if (notifyMap.containsKey("aliAmount")) {
            payCost = new BigDecimal(notifyMap.get("aliAmount"));
        } else if (notifyMap.containsKey("balanceAmount")) {
            payCost = new BigDecimal(notifyMap.get("balanceAmount"));
        } else {
            throw new BusinessException("没有此订单！");
        }
        example.createCriteria().andEqualTo("paySn", notifyMap.get("paySn"))
                .andEqualTo("payStatus", OrderConstants.OrderPayStatusEnum.PRE_PAY.getValue())
                .andEqualTo("orderStatus", OrderConstants.OrderStatusEnum.PRE_PAY.getValue())
                .andEqualTo("payAmount", payCost);
        example.selectProperties("id", "productId","paySn", "shopId", "amount", "orderSn", "memberId", "payAmount", "giftCredit","giftAmount");
        try {
            HashMap<String,String> orderNotifyParam = new HashMap<>();//充值订单消息通知
            HashMap<String,String> balanceNotifyParam = new HashMap<>();//余额变动消息通知
            List<MemberRechargeOrderDO> orderList = rechargeOrderMapper.selectByExample(example);
            if(orderList.size()!=1){
                return;
            }
            MemberRechargeOrderDO orderInfo = orderList.get(0);
            //TODO:修改订单状态,支付状态,支付时间
            rechargeOrderMapper.paySuccessHandle(orderInfo.getPaySn());
            //TODO:获取会员余额
            MemberDO memberAsset = memberMapper.getAssetById(orderInfo.getMemberId());
            BigDecimal changeBalance = orderInfo.getAmount().add(BigDecimal.valueOf(orderInfo.getGiftAmount()));
            BigDecimal newBalance = memberAsset.getBalance().add(changeBalance);
            BigDecimal newTotalRechargeAmount = memberAsset.getTotalRechargeAmount().add(orderInfo.getAmount());
            Integer newCredit = memberAsset.getCredit() + orderInfo.getGiftCredit();
            //TODO:修改会员余额、累计充值金额、积分
            MemberDO memberUpdate = new MemberDO();
            memberUpdate.setId(orderInfo.getMemberId());
            memberUpdate.setBalance(newBalance);
            memberUpdate.setTotalRechargeAmount(newTotalRechargeAmount);
            memberUpdate.setCredit(newCredit);
            memberUpdate.setLastConsumeTime(new Date());
            memberMapper.updateByPrimaryKeySelective(memberUpdate);
            //TODO:修改商品销量
            productMapper.saleIncrement(orderInfo.getProductId());
            productMapper.shopSaleIncrement(orderInfo.getShopId(),orderInfo.getProductId());
            //TODO:插入余额变动记录
            MemberBalanceRecordDO memberBalanceRecordDO = new MemberBalanceRecordDO();
            memberBalanceRecordDO.setShopId(orderInfo.getShopId());
            memberBalanceRecordDO.setRecordSn(OrderConstants.SnPrefix.BALANCE_MEMBER.getValue() + time + NumberUtils.generateCode(4));
            memberBalanceRecordDO.setType(MemberRechargeConstants.TypeEnum.SYSTEM_INSERT.getValue());
            memberBalanceRecordDO.setChangeType(MemberRechargeConstants.ChangeTypeEnum.INCREASE.getValue());
            memberBalanceRecordDO.setLinkModel(MemberRechargeConstants.LinkModelEnum.RECHARGE.getValue());
            memberBalanceRecordDO.setLinkSn(orderInfo.getOrderSn());
            memberBalanceRecordDO.setMemberId(orderInfo.getMemberId());
            memberBalanceRecordDO.setOldBalance(memberAsset.getBalance());
            memberBalanceRecordDO.setChangeBalance(changeBalance);
            memberBalanceRecordDO.setNewBalance(newBalance);
            memberBalanceRecordDO.setRemark("充值成功,实付金额:" + orderInfo.getPayAmount() + "元"
                    + "，赠送金额：" + orderInfo.getGiftAmount()+"元"
                    + "，到账金额：" + changeBalance + "元"
                    + "，支付单号：" + orderInfo.getPaySn());
            memberBalanceRecordDO.setCreateBy("充值订单支付回调");
            memberBalanceRecordDO.setCreateTime(new Date());
            balanceRecordMapper.insertSelective(memberBalanceRecordDO);
            //余额变动-消息通知
            balanceNotifyParam.put("isInfo","Y");
            balanceNotifyParam.put("templateKey","balanceChange");
            balanceNotifyParam.put("shopId",memberBalanceRecordDO.getShopId().toString());
            balanceNotifyParam.put("linkModelDesc",MemberRechargeConstants.LinkModelEnum.RECHARGE.getValueDesc());
            balanceNotifyParam.put("linkSn",memberBalanceRecordDO.getLinkSn());
            balanceNotifyParam.put("changeBalance","+"+memberBalanceRecordDO.getChangeBalance().toString());
            balanceNotifyParam.put("newBalance",memberBalanceRecordDO.getNewBalance().toString());
            balanceNotifyParam.put("createTime",DateUtils.getTime());
            balanceNotifyParam.put("balanceChangeRemark",memberBalanceRecordDO.getRemark());

            if (orderInfo.getGiftCredit() > 0) {
                //TODO:积分变动
                MemberCreditRecordDO memberCreditRecordDO = new MemberCreditRecordDO();
                memberCreditRecordDO.setShopId(orderInfo.getShopId());
                memberCreditRecordDO.setRecordSn(OrderConstants.SnPrefix.CREDIT_MEMBER.getValue() + time + NumberUtils.generateCode(4));
                memberCreditRecordDO.setType(MemberCreditConstants.TypeEnum.SYSTEM_INSERT.getValue());
                memberCreditRecordDO.setChangeType(MemberCreditConstants.ChangeTypeEnum.INCREASE.getValue());
                memberCreditRecordDO.setLinkModel(MemberCreditConstants.LinkModelEnum.RECHARGE.getValue());
                memberCreditRecordDO.setLinkSn(orderInfo.getOrderSn());
                memberCreditRecordDO.setMemberId(orderInfo.getMemberId());
                memberCreditRecordDO.setOldCredit(memberAsset.getCredit());
                memberCreditRecordDO.setChangeCredit(orderInfo.getGiftCredit());
                memberCreditRecordDO.setNewCredit(newCredit);
                memberCreditRecordDO.setRemark("会员充值赠送积分,充值:" + orderInfo.getAmount() + "元"
                        + "，赠送：" + orderInfo.getGiftCredit() + "分"
                        + "，充值单号：" + orderInfo.getOrderSn());
                memberCreditRecordDO.setCreateBy("会员充值赠送积分");
                memberCreditRecordDO.setCreateTime(new Date());
                creditRecordMapper.insertSelective(memberCreditRecordDO);
                orderNotifyParam.put("creditRemark","会员充值赠送"+orderInfo.getGiftCredit()+"积分");
            }
            //充值订单-消息通知
            orderNotifyParam.put("isInfo","Y");
            orderNotifyParam.put("templateKey","recharge");
            orderNotifyParam.put("orderSn",orderInfo.getOrderSn());
            orderNotifyParam.put("shopId",orderInfo.getShopId().toString());
            orderNotifyParam.put("orderStatusDesc", "充值成功");
            orderNotifyParam.put("amount",orderInfo.getAmount().toString()+"元");
            orderNotifyParam.put("payTime",DateUtils.getTime());
            orderNotifyParam.put("openid",memberAsset.getOpenid());
            orderNotifyParam.put("phone",memberAsset.getPhone());
            orderNotifyParam.put("smsVar",orderInfo.getAmount().toString()+","+memberBalanceRecordDO.getNewBalance().toString());
            //微信模板通知
            AsyncManager.me().execute(ApiAsyncFactory.sendWechatTemplateNotify(orderNotifyParam));
            if(balanceNotifyParam.containsKey("balanceChangeRemark")){
                balanceNotifyParam.put("openid",memberAsset.getOpenid());
                AsyncManager.me().execute(ApiAsyncFactory.sendWechatTemplateNotify(balanceNotifyParam));
            }
            //短信通知
            AsyncManager.me().execute(ApiAsyncFactory.sendSmsNotify(orderNotifyParam));
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("没有此订单！");
        }
    }


}
